#include 	"../includes.h"
#include "udp_includes.h"


int net_open(UDP_DAEMON_* ud)
{
int temp;
struct sockaddr_in addr;
uint16_t bind_port = UDP_PORT,t;


	if((ud->net.sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){
		udp_printf("failed to initalize socket\n");
    	return FAIL;
	}

	/* udp checksum */
	temp = 0;
	if(setsockopt(ud->net.sock, SOL_SOCKET, SO_NO_CHECK, &temp, sizeof(int)) < 0){
		udp_printf("failed to set socket udp checksum\n");
		return FAIL;
	}

	temp = 1;  /* allow address reuse */
	if(setsockopt(ud->net.sock, SOL_SOCKET, SO_REUSEADDR, &temp, sizeof(int)) < 0){
		udp_printf("failed to set socket reuse\n");
		return FAIL;
	}

/* bind sockets */
	/* need INADDR_ANY to allow receipt of multicast and unicast messages */
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	//addr.sin_port = htons(UDP_PORT);
	
	t = strtoul(sicf.v[M_IP_CFG_Source_PORT_INDEX],NULL,0);
	if( t ){ bind_port = t ;  }
	addr.sin_port = htons(bind_port);
	if(bind(ud->net.sock, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0){
		udp_printf("failed to bind socket\n");
		return FAIL;
	}
	printf("---socket open:%d OK\n",(int)bind_port);

	/* make timestamps available through recvmsg() */
	temp = 1;
	if(setsockopt(ud->net.sock, SOL_SOCKET, SO_TIMESTAMP, &temp, sizeof(int)) == -1){
		udp_printf("failed to set socket reuse SO_TIMESTAMP\n");
		return FAIL;
	}

	return OK;
}


int net_close(UDP_DAEMON_* ud)
{
	if(ud->net.sock > 0){
    	close(ud->net.sock);
    }

    ud->net.sock = 0;

    return OK;
}


int net_select(UDP_DAEMON_* ud, TIME_INTERNAL_* timeout)
{
fd_set readfds;
struct timeval tv;

	if(timeout < 0){
		return FAIL;
	}

	FD_ZERO(&readfds);
	FD_SET(ud->net.sock, &readfds);

	tv.tv_sec = timeout->seconds;
	tv.tv_usec = timeout->nanoseconds/1000;

	return select(ud->net.sock + 1, &readfds, 0, 0, &tv);
	//return select(ud->net.sock + 1, &readfds, 0, 0, NULL);
}


int net_recv(UDP_DAEMON_* ud)
{

struct msghdr msg;
struct iovec vec[1];
struct sockaddr_in from_addr;
union {
	struct cmsghdr cm;
    char data[CMSG_SPACE(sizeof(struct timeval))];
} cmsg_un;


	vec[0].iov_base = ud->net.ibuf;
	vec[0].iov_len = PACKET_SIZE;

	memset(&msg, 0, sizeof(msg));
	memset(&from_addr, 0, sizeof(from_addr));
	memset(ud->net.ibuf, 0, PACKET_SIZE);
	memset(&cmsg_un, 0, sizeof(cmsg_un));

	msg.msg_name = (caddr_t)&from_addr;
	msg.msg_namelen = sizeof(from_addr);
	msg.msg_iov = vec;
	msg.msg_iovlen = 1;
	msg.msg_control = cmsg_un.data;
	msg.msg_controllen = sizeof(cmsg_un.data);
	msg.msg_flags = 0;

	//ud->net.ibuf_len = recvmsg(ud->net.sock, &msg, MSG_DONTWAIT);
	ud->net.ibuf_len = recvmsg(ud->net.sock, &msg, MSG_WAITALL);

	if(ud->net.ibuf_len <= 0){
		return FAIL;
	}

	if((msg.msg_controllen < sizeof(struct cmsghdr)) || (msg.msg_flags & MSG_CTRUNC)){
		udp_printf("short or truncated cmsghdr!(%d)\n",(msg.msg_flags & MSG_CTRUNC));
		return FAIL;
	}


	strncpy(ud->net.raddr_temp, inet_ntoa(from_addr.sin_addr), NET_ADDRESS_LENGTH-1);
	udp_printf("rcv, raddr:%s\n",ud->net.raddr_temp );
	ud->net.rport_temp = ntohs(from_addr.sin_port);

	return OK;
}

extern int debug_send_local;

int8 	str_ip_server[NET_ADDRESS_LENGTH+2];
//int16u 	port_server = UDP_PORT;


//int net_send(UDP_DAEMON_* ud, unsigned int length, int debug_send)
int net_send(char * p, unsigned int length, int debug_send)
{
struct sockaddr_in addr;
int index;
	UDP_DAEMON_* ud=&udp;
	addr.sin_family = AF_INET;
	//inet_aton(ud->net.raddr_temp, &addr.sin_addr);
	//inet_aton(str_ip_server, &addr.sin_addr);
	inet_aton(sicf.v[M_IP_CFG_Remote_IP_INDEX], &addr.sin_addr);

	//inet_aton("183.98.119.157", &addr.sin_addr);  //test
	//udp_printf(">ip>:%s,%s\n",str_ip_server);
	udp_printf(">>>>>ip>:%s >>>port:%s \n",sicf.v[M_IP_CFG_Remote_IP_INDEX], sicf.v[M_IP_CFG_Remote_PORT_INDEX] );

	//addr.sin_port = htons(14000);
	//addr.sin_port = htons(port_server);
	addr.sin_port = htons( strtoul(sicf.v[M_IP_CFG_Remote_PORT_INDEX],NULL,0) );

	//udp_printf("\nsend packet, raddr:%s(0x%X)\n", ud->net.raddr_tem,(int)htons(addr.sin_addr );

	udp_printf("\n%2d:%2d:%2d>>send packet, raddr:%s(0x%X), port:%d, len:%d\n"
			,SYSTEM.TIME.CUR.HOUR,SYSTEM.TIME.CUR.MINUTE,SYSTEM.TIME.CUR.SECOND
			,sicf.v[M_IP_CFG_Remote_IP_INDEX] //, ud->net.raddr_temp
			, addr.sin_addr.s_addr
			,(int)htons(addr.sin_port) ,length);

	//if(sendto(ud->net.sock, ud->net.obuf, length, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0){
	if(sendto(ud->net.sock, p, length, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0){
		udp_printf("error sending udp message\n");
		return FAIL;
	}


	//udp_printf("%c[7m",0x1B);
	udp_MemoryHexDump(p,length);
	//udp_printf("%c[0m\n",0x1B);


	return OK;
}


